﻿#region Copyright Info

// 
// Majesty of Omega - The next evolution of macro management space strategy
// 
// Copyright 2007-2009 André Claaßen
// 
// This file is protected by the terms and conditions of the
// Microsoft Community License (Ms-CL 1.1), a copy of which should
// have been distributed along with this software. If not,
// you may find the license information at the following URL:
// 
// http://www.microsoft.com/resources/sharedsource/licensingbasics/communitylicense.mspx

#endregion

#region

using System;
using System.ComponentModel;
using System.Windows.Controls;
using DesignByContract;
using Majesty_of_Omega.Config;
using Majesty_of_Omega.Logic.Calculate;
using Majesty_of_Omega.Logic.GameConfiguration;
using Majesty_of_Omega.Model.Space;
using Majesty_of_Omega.Model.Game;
using Majesty_of_Omega.GUI.Pages.Game;
using Majesty_of_Omega.GUI.Pages.Game.Research;
using System.Windows;
using Majesty_of_Omega.GUI.Pages.Game.SitReport;
using Majesty_of_Omega.Model.Report;

#endregion

namespace Majesty_of_Omega.GUI.Controller
{
    /// <summary>
    /// The general gameplay controller. The controller controls the behaviour of the in game screens
    /// </summary>
    public class GalaxyPageController : InGameController, INotifyPropertyChanged
    {
        /// <summary>
        /// Gets the galaxy page.
        /// </summary>
        /// <value>The galaxy page.</value>
        private GalaxyPage GalaxyPage
        {
            get
            {
                Require.IsNotNull("This property should only be used, when a Page is associated with this controller");
                return (GalaxyPage)Page;
            }
        }

        /// <summary>
        /// Constructs the game play controller with the given game
        /// </summary>
        public GalaxyPageController(SaveGame saveGame) : base(saveGame)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="GalaxyPageController"/> class.
        /// </summary>
        public GalaxyPageController()
        {
            
        }

        ///<summary>
        /// This property shows the formatted Turn Number for xaml binding
        ///</summary>
        public string TurnNumberFormatted
        {
            get { return string.Format("Turn {0:D3}", saveGame.TurnNumber); }
        }

        /// <summary>
        /// Gets the research points as formatted string.
        /// </summary>
        /// <value>The research points formatted.</value>
        public string ResearchPointsFormatted
        {
            get
            {
                return saveGame.HumanPlayer.ResearchManager.TotalResearchPointsOfCurrentTurn.ToString();
            }
        }

        /// <summary>
        /// Gets the galaxy.
        /// </summary>
        /// <value>The galaxy.</value>
        public StarGalaxy Galaxy
        {
            get
            {
                return saveGame.Galaxy;
            }
        }

        /// <summary>
        /// Calculates the next turn of the game
        /// </summary>
        public void NextTurn()
        {
            NextTurnCalculator nextTurnCalculator = new NextTurnCalculator(saveGame);
            nextTurnCalculator.CalculateNextTurn();
            Ensure.IsTrue(saveGame.TurnNumber > 0, "The number of played turns must be at least one");
            InvokePropertyChanged("TurnNumberFormatted");
            InvokePropertyChanged("ResearchPointsFormatted");
            GotoSituationReport();
        }

        private void InvokePropertyChanged(string property)
        {
            if (PropertyChanged != null)
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(property));
        }

        /// <summary>
        /// Create dummy game play controller for editing purposes in blend. The Controller has a dummy SaveGame
        /// </summary>
        /// <returns>a new galaxy screen controller for testing and editing (in blend) purposes</returns>
        public static GalaxyPageController CreateDummyGamePlayController()
        {
            GameSettings settings = new GameSettings
                                        {
                                            GalaxyConfigurationByName = "2 - Arms Galaxy",
                                            EmpireName = "Blend Test Empire"
                                        };
            GameGenerator generator = new GameGenerator(settings);
            return new GalaxyPageController(generator.GenerateNewGame());
        }

        /// <summary>
        /// Saves the current game.
        /// </summary>
        public void SaveCurrentGameAction()
        {
            var gameManager = new SaveGameManager();
            gameManager.Save(saveGame, gameManager.GetDefaultFilename(saveGame));
        }

        /// <summary>
        /// Goto to the star system page for the given star.
        /// </summary>
        /// <param name="star">The star in the galaxy.</param>
        public StarSystemPage GotoStarSystemPage(Star star)
        {
            StarSystemPage pageStarSystem = new StarSystemPage(new StarSystemPageController(star, saveGame));
            SubFrameNavigateTo(pageStarSystem);
            return pageStarSystem;
        }

        /// <summary>
        /// This event will be raised, if one of the xaml bound properties changed. 
        /// </summary>
        /// <see>TurnNumberFormatted</see>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Navigate to a new page. The XAML-Page is a view in the model view controller context
        /// </summary>
        /// <param name="target">The target.</param>
        protected void SubFrameNavigateTo(Page target)
        {
            if (GalaxyPage == null) return;
            GalaxyPage.EnableTrackball(target == null);
            GalaxyPage.GreyRectangle.Visibility = Visibility.Hidden;
            GalaxyPage.IsHitTestVisible = true;
            GalaxyPage.StatusIconsGrid.Visibility = (target == null) ? Visibility.Visible : Visibility.Hidden;
            GalaxyPage.GameMenuFrame.Navigate(target);
        }

        /// <summary>
        /// Goto to the research page.
        /// </summary>
        public void GotoResearchPage(SitReportEntry entry)
        {
            SubFrameNavigateTo(new ResearchPage(new ResearchPageController(saveGame, entry)));
        }

        /// <summary>
        /// Hides the in game menue and make the stars clickable
        /// </summary>
        public void OnCancelMenu()
        {
            SubFrameNavigateTo(null);
        }

        /// <summary>
        /// Shows the Save Game Page
        /// </summary>
        public void OnSaveGame()
        {
            SubFrameNavigateTo(new SavePage(this));
        }

        /// <summary>
        /// Show the situation report
        /// </summary>
        public void GotoSituationReport()
        {
            SubFrameNavigateTo(new SitReportPage(new SitReportController(Game)));
        }

        /// <summary>
        /// Someone wants to navigate to a new location.
        /// The main source of hyperlinks comes from the SitReportPage.
        /// </summary>
        /// <param name="reportEntry">The report entry.</param>
        public void NavigateToSitreportEntryLink(SitReportEntry reportEntry)
        {
            switch (reportEntry.ReportType)
            {
                case SitReportType.TurnCompleted:
                    break;
                case SitReportType.TurnCompletedTest:
                    break;
                case SitReportType.ResearchBreakthroughOnField:
                case SitReportType.ResearchUnlockTechField:
                case SitReportType.NewTechnologyUncovered:
                case SitReportType.TechnologyProjectResearchStarted:
                case SitReportType.TechnologyProjectResearched:
                case SitReportType.TechnologyReachedPrototypeState:
                case SitReportType.TechnologyProjectResearchedWithPositiveOverrun:
                case SitReportType.TechnologyProjectRoadblockOccured:
                    GotoResearchPage(reportEntry);
                    break;
                default:
                    throw new ArgumentOutOfRangeException("reportEntry");
            }
        }
    }
}